package com.codefish.framework.spring.context.annotation;

import com.codefish.framework.spring.beans.factory.support.BeanDefinition;
import com.codefish.framework.spring.beans.factory.support.IBeanDefinitionRegistry;
import com.codefish.framework.spring.context.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * 将扫描到的组件注册到BeanDefinitionRegistry中
 *
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/11/05 下午 12:45
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    IBeanDefinitionRegistry registry;
    IBeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;

    public ClassPathBeanDefinitionScanner(IBeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public int scanComponents(Set<String> basePackages) {
        int preCnt = getRegistry().getBeanDefinitionCount();
        doScanComponents(basePackages);
        int afterCnt = getRegistry().getBeanDefinitionCount();
        return afterCnt - preCnt;
    }

    protected Set<BeanDefinition> doScanComponents(Set<String> basePackages) {
        Set<BeanDefinition> mergedBeanDefinitions = new HashSet<>();
        for (String basePackage : basePackages) {
            Set<BeanDefinition> beanDefinitions = scanCandidateComponent(basePackage);
            mergedBeanDefinitions.addAll(beanDefinitions);
        }
        for (BeanDefinition beanDefinition : mergedBeanDefinitions) {
            String beanName = beanNameGenerator.generateBeanName(beanDefinition);
            getRegistry().registerBeanDefinition(beanName, beanDefinition);
        }
        return mergedBeanDefinitions;
    }


    @Override
    protected BeanDefinition generateBeanDefinition(Class<?> bdClass) {
        Component component = bdClass.getAnnotation(Component.class);
        Scope scope = bdClass.getAnnotation(Scope.class);
        if (component == null) {
            return null;
        }
        BeanDefinition bd = new BeanDefinition(bdClass);
        if (scope != null) {
            bd.setScope(scope.value());
        }
        return bd;
    }

    @Override
    public IBeanDefinitionRegistry getRegistry() {
        return registry;
    }

    public void setBeanNameGenerator(IBeanNameGenerator beanNameGenerator) {
        this.beanNameGenerator = beanNameGenerator;
    }

    public IBeanNameGenerator getBeanNameGenerator() {
        return beanNameGenerator;
    }
}
